﻿// -----------------------------------------------------------------------
// <copyright file="FileAssociation.cs" company="Abyssalsoft">
// TODO: Update copyright text.
// </copyright>
// -----------------------------------------------------------------------

namespace Metal.Config
{
    using System;
    using System.Collections.Generic;
    using System.Runtime.InteropServices;
    using System.Text;
    using Metal.User;
    using Microsoft.Win32;

    /// <summary>
    /// Used to associate file types with Metal Player
    /// </summary>
    public static class FileAssociation
    {
        /// <summary>SHChangeNotify API</summary>
        /// <param name="wEventId">Win. Event ID</param>
        /// <param name="uFlags">Flags value</param>
        /// <param name="dwItem1">Pointer - not used</param>
        /// <param name="dwItem2">Pointer2 - not used</param>
        [DllImport("shell32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern void SHChangeNotify(uint wEventId, uint uFlags, IntPtr dwItem1, IntPtr dwItem2);

        /// <summary>Notify Windows about our changes</summary>
        public static void NotifyChanges()
        {
            SHChangeNotify(0x08000000, 0x00000800, IntPtr.Zero, IntPtr.Zero);
        }

        /// <summary>Associate extension with Metal Player</summary>
        /// <param name="extension">Extension to be opened with Metal Player</param>
        /// <param name="description">Description of extension</param>
        /// <param name="icon">The icon to be used with this extension</param>
        public static void AssociateExtension(string extension, string description, string icon)
        {
            string exeName = System.AppDomain.CurrentDomain.FriendlyName;
            SetAssociation(extension, exeName + icon, System.Windows.Forms.Application.ExecutablePath, description, Paths.IconsFolder + icon); 
        }

        public static void SetAssociation(string Extension, string KeyName, string OpenWith, string FileDescription, string icon)
        {
            try
            {
                RegistryKey BaseKey;
                RegistryKey OpenMethod;
                RegistryKey Shell;
                RegistryKey CurrentUser;

                BaseKey = Registry.ClassesRoot.CreateSubKey(Extension);
                BaseKey.SetValue("", KeyName);

                OpenMethod = Registry.ClassesRoot.CreateSubKey(KeyName);
                OpenMethod.SetValue("", FileDescription);
                OpenMethod.CreateSubKey("DefaultIcon").SetValue(string.Empty, ToShortPathName(icon));
                Shell = OpenMethod.CreateSubKey("Shell");
                Shell.CreateSubKey("edit").CreateSubKey("command").SetValue("", "\"" + OpenWith + "\"" + " \"%1\"");
                Shell.CreateSubKey("open").CreateSubKey("command").SetValue("", "\"" + OpenWith + "\"" + " \"%1\"");
                BaseKey.Close();
                OpenMethod.Close();
                Shell.Close();

                // Delete the key instead of trying to change it
                CurrentUser = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\" + Extension, true);
                CurrentUser.DeleteSubKey("UserChoice", false);
                CurrentUser.Close();

                // Tell explorer the file association has been changed
                SHChangeNotify(0x08000000, 0x0000, IntPtr.Zero, IntPtr.Zero);
            }
            catch
            {
            }
        }

        /// <summary>Get short path name API</summary>
        /// <param name="lpszLongPath">String long path</param>
        /// <param name="lpszShortPath">String short path</param>
        /// <param name="cchBuffer">Buffer size</param>
        /// <returns>Returns short path name</returns>
        [DllImport("Kernel32.dll")]
        private static extern uint GetShortPathName(string lpszLongPath, [Out] StringBuilder lpszShortPath, uint cchBuffer);

        /// <summary>Return short path format of a file name</summary>
        /// <param name="longName">Long file name</param>
        /// <returns>Returns short file name</returns>
        private static string ToShortPathName(string longName)
        {
            StringBuilder s = new StringBuilder(1000);
            uint iSize = (uint)s.Capacity;
            uint iRet = GetShortPathName(longName, s, iSize);
            return s.ToString();
        }
    }
}
